﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using MediaData;
using System.Text.RegularExpressions;

namespace MediaData
{
    public class AnimeScanner : MediaItemScanner
    {
        public AnimeScanner(string type) : base(type) { }

        public override void Scan(MediaRoot root, Predicate<MediaItem> exists, Action<MediaItem> mediaAdded)
        {
            List<string> showDirs = new List<string>();

            foreach (string groupDir in Directory.GetDirectories(Path.Combine(root.Path, this.Type)))
            {
                string group = Path.GetFileName(groupDir);
                if (group.StartsWith(".") || group.StartsWith("_"))
                    continue;

                // If group dir available
                if (group.StartsWith("#"))
                    showDirs.AddRange(Directory.GetDirectories(groupDir));
                else
                    showDirs.Add(groupDir);
            }

            foreach (var titleDir in showDirs)
            {
                string titleName = Path.GetFileName(titleDir);
                if (titleName.StartsWith("."))
                    continue;

                foreach (string file in Directory.GetFiles(titleDir, "*.*", SearchOption.AllDirectories))
                {
                    MediaType mediaType = this.GetType(Path.GetFileName(file));
                    if (mediaType != MediaType.Video && mediaType != MediaType.DiscImage)
                        continue;


                    MediaItem v = new MediaItem(root.Volume, file);

                    if (exists == null || !exists(v))
                    {
                        ParseAnimeFilename(v, file);

                        v.Title = titleName;
                        v.Type = this.Type;

                        mediaAdded(v);
                    }
                }
            }
        }
        public static void ParseAnimeFilename(MediaItem video, string file)
        {
            string crc = "", ver = "0", grp = "", ep = "", tail = "", head = ""; ;

            Regex crcPattern = new Regex("(?i)([^A-Z0-9]([A-Z0-9]{8})[^A-Z0-9])");
            Regex crcPattern2 = new Regex(@"(?i)(\(|\[)([A-Z0-9]{8})(\)|\])");
            Regex crcCheckPattern = new Regex("[0-9]+");

            Regex grpStartPattern = new Regex(@"^(\(|\[)([^\(\[\]\)]+)(\)|\]).*?");
            Regex grpEndPattern = new Regex(@".*?(\(|\[)([^\(\[\]\)]+)(\)|\])$");

            Regex boxedPattern = new Regex(@".*?(\(|\[)([^\(\[\]\)]+)(\)|\]).*?");

            Regex versionPattern = new Regex("(?i).*?[^A-Z](v[0-9])([^A-Z0-9]|$).*?");

            Regex[] episodePattern = new Regex[7];
            episodePattern[0] = new Regex(@"(?i)(.*?)(\W|^)(\d{1,3}-\d{1,3})(\W|$)(.*?)");
            episodePattern[1] = new Regex(@"(?i)(.*?)(\W|^)(\d{1,3}\s*&\s*\d{1,3})(\W|$)(.*?)");
            episodePattern[2] = new Regex(@"(?i)(.*?)(\W|^)(ep\s*(\d{1,3}))(\W|$)(.*?)");
            episodePattern[3] = new Regex(@"(?i)(.*?)(\W|^)(episode\s*(\d{1,3}))(\W|$)(.*?)");
            episodePattern[4] = new Regex(@"(?i)(.*?)(\W|^)(ep[A-Z]*\s*(\d{1,3}))(\W|$)(.*?)");
            episodePattern[5] = new Regex(@"(.*?)(\W|^)(\d{1,3})(\W\D+$|$)");
            episodePattern[6] = new Regex(@"(.*?)(\W|^)(\d{1,3})(\W|$)(.*?)");

            Regex episodeNumberPattern = new Regex(@"^.*?(\d+).*?$");

            string name = Path.GetFileNameWithoutExtension(file);
            Match m;

            if ((m = crcPattern2.Match(name)).Success)
            {

                while (!crcCheckPattern.IsMatch(m.Groups[2].ToString()) && (m = m.NextMatch()).Success) { }

                if (m.Success)
                {
                    name = name.Replace(m.Groups[1].ToString() + m.Groups[2].ToString() + m.Groups[3].ToString(), "");
                    crc = m.Groups[2].ToString();
                }
            }
            if (crc.Length == 0 && (m = crcPattern.Match(name)).Success)
            {
                while (!crcCheckPattern.IsMatch(m.Groups[2].ToString()) && (m = m.NextMatch()).Success) { }

                if (m.Success)
                {
                    name = name.Replace(m.Groups[1].ToString(), "");
                    crc = m.Groups[2].ToString();
                }
            }

            if ((m = grpStartPattern.Match(name)).Success)
            {
                name = name.Replace(m.Groups[1].ToString() + m.Groups[2].ToString() + m.Groups[3].ToString(), "");
                grp = m.Groups[2].ToString();
            }
            else
            {
                if ((m = grpEndPattern.Match(name)).Success)
                {
                    name = name.Replace(m.Groups[1].ToString() + m.Groups[2].ToString() + m.Groups[3].ToString(), "").Trim();
                    grp = m.Groups[2].ToString();
                }
            }

            name = name.Replace(".", " ").Replace("_", " ").Trim();
            Regex.Replace(name, @"\s{2,}", " ");

            if ((m = versionPattern.Match(name)).Success)
            {
                name = name.Replace(m.Groups[1].ToString(), "");
                ver = m.Groups[1].ToString().Substring(1);
            }



            List<string> more = new List<string>();
            while ((m = boxedPattern.Match(name)).Success)
            {
                name = name.Replace(m.Groups[1].ToString() + m.Groups[2].ToString() + m.Groups[3].ToString(), "");
                more.Add(m.Groups[2].ToString());
            }



            for (int j = 0; j < episodePattern.Length; j++)
            {
                if ((m = episodePattern[j].Match(name)).Success)
                {
                    head = Regex.Replace(Regex.Replace(m.Groups[1].ToString(), @"(?i)[^A-Z0-9 !~\+-=']+", ""), @"\s+[^\w]+$", "").Trim();
                    switch (j)
                    {
                        case 0:
                        case 1:
                        case 6:
                            name = name.Replace(m.Groups[2].ToString() + m.Groups[3].ToString() + m.Groups[4].ToString(), "");
                            tail = m.Groups[5].ToString();
                            if (j < 2)
                            {
                                List<string> al = new List<string>();
                                ep = m.Groups[3].ToString();
                                while ((m = episodeNumberPattern.Match(ep)).Success)
                                {
                                    al.Add(m.Groups[1].ToString());
                                    ep = ep.Replace(m.Groups[1].ToString(), "");
                                }
                                ep = "";
                                for (int i = 0; i < al.Count; i++)
                                {
                                    if (i != 0)
                                        ep += "-";
                                    ep += al[i];
                                }
                            }
                            else
                            {
                                ep = m.Groups[3].ToString();
                            }
                            break;
                        case 5:
                            name = name.Replace(m.Groups[2].ToString() + m.Groups[3].ToString() + m.Groups[4].ToString(), "");
                            ep = m.Groups[3].ToString();
                            tail = m.Groups[4].ToString();
                            break;
                        case 2:
                        case 3:
                        case 4:
                            name = name.Replace(m.Groups[2].ToString() + m.Groups[3].ToString() + m.Groups[5].ToString(), "");
                            tail = m.Groups[6].ToString();
                            ep = m.Groups[4].ToString();
                            m = episodeNumberPattern.Match(ep);
                            ep = m.Groups[1].ToString();
                            break;

                    }
                    break;
                }
            }
            //            int version = ver.Length > 0 ? Int32.Parse(ver) : 1;
            //            tail = tail.Trim().Length > 0 ? Regex.Replace(tail, @"\W", " ").Trim() : "";

            //video.title = head != "" ? head : Regex.Replace(Regex.Replace(Regex.Replace(name, @"(?i)[^A-Z0-9 !~\+-=]+", ""), @"\s{2,}", " "), @"\s+[^\w]+$", "").Trim();
            //video.encoder = grp;
            //video.crc = crc;
            //video.comment = String.Join(", ", more.ToArray());
            if (Regex.IsMatch(ep, @"\d{1,3}-\d{1,3}"))
            {
                string[] h = ep.Split(new char[] { '-' });
                video.Episode = Int32.Parse(h[0]);
                video.LastEpisode = Int32.Parse(h[1]);
            }
            else if (ep != "")
            {
                video.Episode = Int32.Parse(ep);
                video.LastEpisode = video.Episode;
            }
        }
    }
}
